﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ExpositionInstrument.cs" company="">
//   
// </copyright>
// <summary>
//   The instrument exposition.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using System;
using Systemathics.FrameWork.Interfaces;

namespace Systemathics.FrameWork
{
    public sealed class InstrumentExposition : IExpositionInstrument, IDisposable
    {
        private readonly Instrument i;

        public InstrumentExposition(Instrument instrument)
        {
            i = instrument;
            BoughtPrice = 0;
            BoughtQty = 0;
            SoldQty = 0; 
            SoldPrice = 0;
        }

        public void Add(OrderSide side, int qty, Decimal price)
        {
            lock (this)
            {
                switch (side)
                {
                    case OrderSide.Buy:
                        if (BoughtQty + qty <= 0) BoughtPrice = price;
                        else BoughtPrice = (BoughtPrice * BoughtQty + price * qty) / (BoughtQty + qty);

                        BoughtQty += qty;
                        break;
                    case OrderSide.Sell:
                        if (SoldQty + qty <= 0) SoldPrice = price;
                        else SoldPrice = (SoldPrice * SoldQty + price * qty) / (SoldQty + qty);

                        SoldQty += qty;
                        break;
                }
            }
        }
        
        #region IExpositionInstrument Members

        public void Init()
        {
            BoughtPrice = 0;
            BoughtQty = 0;
            SoldQty = 0;
            SoldQty = 0;
        }
        public DateTime EntryDate { get; set; }
        public TimeSpan Duration { get { return Time.Now - EntryDate; } }
        public Decimal BalancePrice
        {
            get { return (Balance != 0) ? ((Balance > 0) ? BoughtPrice : SoldPrice) : 0; }
        }
        public Decimal BoughtPrice { get; private set; }
        public int BoughtQty { get; private set; }
        public Decimal SoldPrice { get; private set; }
        public int SoldQty { get; private set; }
        public int Balance { get { return BoughtQty - SoldQty; } }
        public Decimal PL { get { return Realized + UnRealized; } }
        public double NetExposedNominal { get { return LongExposedNominal - ShortExposedNominal; } }
        public double LongExposedNominal
        {
            get { return BoughtQty * (double)BoughtPrice*i.StaticData.Rules.TickValue*i.StaticData.Currency.ReferencePrice; }
        }
        public double ShortExposedNominal { get { return SoldQty * (double)SoldPrice * i.StaticData.Rules.TickValue * i.StaticData.Currency.ReferencePrice; } }
        public Decimal Realized
        {
            get
            {
                return (Decimal) (Math.Min(BoughtQty, SoldQty)*i.StaticData.Rules.TickValue*i.StaticData.Currency.ReferencePrice)*(SoldPrice - BoughtPrice);
            } 
        }
        public Decimal UnRealized
        {
            get
            {
                var reference = Mark2Market();
                if (reference.HasValue)
                    return (Decimal)((BoughtQty - SoldQty) * i.StaticData.Rules.TickValue * i.StaticData.Currency.ReferencePrice) * ((BoughtQty > SoldQty) ? (reference.Value - BoughtPrice) : (reference.Value - SoldPrice));
                return 0;
            }
        }

        #endregion

        private Decimal? Mark2Market()
        {
            if (i.Blotter[QuoteLevel.One].Mid != 0) return i.Blotter[QuoteLevel.One].Mid;
            if (i.Trade.Price != 0) return i.Trade.Price;
            if (i.MarketData.Close != 0) return i.MarketData.Close;
            return Decimal.Zero;
        }

        #region IDisposable Members

        public void Dispose()
        {
            BoughtQty = 0;
            BoughtPrice = 0;
            SoldPrice = 0;
            SoldQty = 0;
        }

        #endregion
    }
}